package com.lemurian.bankdata.action.base;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import org.apache.struts2.ServletActionContext;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

import com.lemurian.bankdata.dto.LogHelper;
import com.lemurian.bankdata.lite.authentication.BankDataPrincipal;
import com.lemurian.bankdata.lite.enums.UserActivityType;
import com.lemurian.bankdata.lite.logger.BankDataLogger;
import com.lemurian.bankdata.lite.struts.Pager;
import com.lemurian.bankdata.lite.struts.PartialList;
import com.lemurian.bankdata.lite.utils.GeneralConstant;
import com.lemurian.bankdata.lite.utils.GlobalFunction;
import com.lemurian.bankdata.services.ActivityLogService;
import com.lemurian.bankdata.services.MenuService;
import com.lemurian.bankdata.utils.BaseAction;
import com.lemurian.entity.Menu;
import com.lemurian.entity.User;
import com.opensymphony.xwork2.Preparable;

public class MenuAction extends BaseAction implements Preparable {

	private static final long serialVersionUID = 1L;

	private BankDataLogger log = BankDataLogger.getLogger(MenuAction.class.getSimpleName());
	
	private Menu menu = new Menu();
	private List<Menu> menus;
	
	private Menu parent;
	private List<Menu> parents;
	
	private int parentId = 0;
	private int id = 0;
	
	private String jsonMessage = "", jsonType = "";
	
	private User user;
	private BankDataPrincipal principal;
	
	@Autowired private MenuService menuService;
	
	@Autowired 
	private ActivityLogService userActivityLogService;
	private LogHelper userActivityLog;
	
	@Override
	public void prepare() throws Exception {
		
		principal = (BankDataPrincipal) getSession().get(GeneralConstant.USER_PRINCIPAL);
		user = principal.getUser();
		
        if (id > 0) {
            menu = menuService.load(id);

        	if (menu != null && menu.getParent() != null) {
        		parentId = menu.getParent().getId();
                log.info("set parentId from " + menu.getParent().getId());
            }
        }
	}
	
	@Override
	public String list() {
		log.info("list Menu");

        setPreviousPage(GeneralConstant.LIST);
        try {

            PartialList<Menu> partialList = menuService.findByCriteria(getStart(), getCount(),
                    getAscDesc().equalsIgnoreCase("desc") ? Order.desc(getOrderBy().length() > 0 ? getOrderBy() : "parent.id") : Order.asc(getOrderBy().length() > 0 ? getOrderBy() : "parent.id"),
                    menu.getName() != null && menu.getName().length() > 0 ? Restrictions.ilike("name", menu.getName(), MatchMode.ANYWHERE) : Restrictions.ne("id", new Integer(-1)),
                    menu.getDescription() != null && menu.getDescription().length() > 0 ? Restrictions.ilike("description", menu.getDescription(), MatchMode.ANYWHERE) : Restrictions.ne("id", new Integer(-1)),
                    menu.getUrl() != null && menu.getUrl().length() > 0 ? Restrictions.like("url", menu.getUrl(), MatchMode.ANYWHERE) : Restrictions.ne("id", new Integer(-1))
                    );

            menus = partialList.getList();

            setPager(Pager.generatePager(getStart(), getCount(), partialList.getTotal()));
            setPagerItem(Pager.generatePagerItem(getStart(), getCount(), partialList.getTotal()));

            partialList = null;
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        setMappedRequest(GeneralConstant.LIST);
        return SUCCESS;
	}
	
	public String add() {
		try {
			
			getSession().put(GeneralConstant.TIME_IN_SESSION, new Date());
			
			if(parents == null || parents.size() ==0)
            parents = menuService.parents();
            log.info("Load list parent");
            
        } catch (Throwable t) {
            t.printStackTrace();
        }

        setMappedRequest(GeneralConstant.SAVE);
        setPreviousPage(GeneralConstant.ADD);
        return SUCCESS;
	}
	
	@Override
	public String save() {

		if(menu.getName() == null || menu.getName().equalsIgnoreCase("")) {
			jsonMessage = "Name is required";
			log.info(jsonMessage);
			addCustomActionError(jsonMessage);
			return INPUT;
			//return GeneralConstant.JSON;
        }

        /*if(menu.getUrl() == null || menu.getUrl().equalsIgnoreCase("") && parentId > 0 || menu.isShowParent() == Boolean.TRUE) {
            //addCustomActionError("URL is required");
            jsonMessage = "URL is required";
            log.info(jsonMessage);
			return GeneralConstant.JSON;
        }*/

        if(menu.getUrl().contains(".do") == false && parentId > 0) {
            jsonMessage = "URL must have .do extension";
            log.info(jsonMessage);
            addCustomActionError(jsonMessage);
            return INPUT;
			//return GeneralConstant.JSON;
        }
		
		String message = "";
		try {
			
			if(id > 0) {
				menu.setUpdateBy(user.getLoginId());
				menu.setUpdateDate(new Timestamp(System.currentTimeMillis()));
				
				message = "Update";
                userActivityLog = new LogHelper(user, UserActivityType.UPDATE_MENU);
			} else {
				menu.setCreateBy(user.getLoginId());
				menu.setCreateDate(new Timestamp(System.currentTimeMillis()));
				
				message = "Add";
                userActivityLog = new LogHelper(user, UserActivityType.ADD_MENU);
			}
			
			menu.setParent(null);
			if(parentId > 0) {
				parent = (Menu) menuService.findById(parentId);
				menu.setParent(parent);
			}
			
			menuService.save(menu);
			log.info("Save Menu ");
			
			try {
                message += " " + menu.getName() + " is success";
                addCustomActionMessage(message);
                
                log.sInfo(" :: User [%s:%s] is successfully save Menu [%s:%s]", user.getId(), user.getName(), menu.getId(), menu.getName());
                userActivityLog.setStatus(LogHelper.SUCCESS_ACTIVITY);
            } catch (Exception e) {
                message += " " + menu.getName() + " is failed, message : "+e.getMessage();
                addCustomActionError(message);
                log.sInfo(" :: Error was raised when User [%s:%s] save Menu [%s:%s]", user.getId(), user.getName(), menu.getId(), menu.getName());
                
                //set activity log status into failed
                userActivityLog.setStatus(LogHelper.FAILED_ACTIVITY);
                userActivityLog.setErrorMsg(e.getMessage());
            }
            
            userActivityLog.setSessionId(ServletActionContext.getRequest().getSession().getId());
            userActivityLog.setStartDate((Date) getSession().get(GeneralConstant.TIME_IN_SESSION));
            userActivityLog.getAdditionalParams().add(menu.getName());
            userActivityLogService.saveUserActivity(userActivityLog);
            getSession().remove(GeneralConstant.TIME_IN_SESSION);
			
		} catch (Throwable t) {
            t.printStackTrace();
            log.info("Error save : " + t.getMessage());
        }
		
		jsonMessage = "message";
        jsonType = "Succes";
		
        setMappedRequestFullPath("MenuAction_list.do");
        return GeneralConstant.REDIRECT;
        //return GeneralConstant.JSON;
	}
	
	@Override
	public String delete() {
		try {
			//menuService.delete(menu);
			menuService.deleteAllParent(menu);
			
			userActivityLog = new LogHelper(user, UserActivityType.DELETE_MENU);
			
			String message = "";
            try {
                message = "Delete " + menu.getName() + " is success";
                addActionMessage(message);
                log.sInfo(" :: User [%s:%s] is successfully delete Menu [%s:%s]", user.getId(), user.getName(), menu.getId(), menu.getName());

                //check if activity is success
                userActivityLog.setStatus(LogHelper.SUCCESS_ACTIVITY);
            } catch (Exception e) {
                message = "Delete " + menu.getName() + " is failed, message : "+e.getMessage();
                addActionError(message);
                log.sInfo(" :: Error was raised when User [%s:%s] delete Menu [%s:%s]", user.getId(), user.getName(), menu.getId(), menu.getName());
                
                //set activity log status into failed
                userActivityLog.setStatus(LogHelper.FAILED_ACTIVITY);
                userActivityLog.setErrorMsg(e.getMessage());
            }
            //save activity log
            userActivityLog.setSessionId(ServletActionContext.getRequest().getSession().getId());
            userActivityLog.getAdditionalParams().add(menu.getName());
            userActivityLogService.saveUserActivity(userActivityLog);
		} catch (Throwable t) {
			addCustomActionError(t.getMessage());
			log.info("Error delete menu : " + t.getMessage());
			t.printStackTrace();
		}
		
		setMappedRequestFullPath("MenuAction_list.do");
		return GeneralConstant.REDIRECT;
	}

	@Override
	public String detail() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String edit() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String update() {
		// TODO Auto-generated method stub
		return null;
	}

	public Menu getMenu() {
		return menu;
	}

	public void setMenu(Menu menu) {
		this.menu = menu;
	}

	public List<Menu> getMenus() {
		return menus;
	}

	public void setMenus(List<Menu> menus) {
		this.menus = menus;
	}

	public Menu getParent() {
		return parent;
	}

	public void setParent(Menu parent) {
		this.parent = parent;
	}

	public List<Menu> getParents() {
		return parents;
	}

	public void setParents(List<Menu> parents) {
		this.parents = parents;
	}

	public int getParentId() {
		return parentId;
	}

	public void setParentId(String parentId) {
		int id_ = 0;
		if(parentId != null && !parentId.equalsIgnoreCase("0")) {
			parentId = GlobalFunction.decodeParameter(parentId);
	        id_ = Integer.parseInt(parentId);
		}
        this.parentId = id_;
	}

	public int getId() {
		return id;
	}

	public void setId(String id) {
		int id_ = 0;
		if(id != null && !id.equalsIgnoreCase("0")) {
			id = GlobalFunction.decodeParameter(id);
	        id_ = Integer.parseInt(id);
		}
        this.id = id_;
	}

	public String getJsonMessage() {
		return jsonMessage;
	}

	public void setJsonMessage(String jsonMessage) {
		this.jsonMessage = jsonMessage;
	}

	public String getJsonType() {
		return jsonType;
	}

	public void setJsonType(String jsonType) {
		this.jsonType = jsonType;
	}
	
}